<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
@font-face {
	font-family: "special";
	src: url(./vermin.ttf);
}
*{
	margin: 0;
	padding: 0;
}
html,body{
}
.container{
	width: 100%;
	display: flex;
	flex-wrap: wrap;
	perspective: 800px;
}
.card{
	position: relative;
	margin: 100px auto;
	width: 500px;
	height: 250px;
	background-color: #29374d;
	background-image: linear-gradient(-135deg,#4b569f -20%,transparent 50%);
	border-radius: 40px;
	box-shadow: 
	0 20px 50px -15px #000 inset,
	0 -20px 50px -25px #ffffff88 inset,
	-2px 1px 3px #000000aa,
	-6px 3px 5px #00000088,
	-20px 8px 20px #00000066;
	color: #a4c0ff;
	text-align: center;
	line-height: 250px;
	font-size: 75px;
	letter-spacing: 2px;
	text-shadow:
	0 2px 1px #ffffff88,
	0 -4px 2px #00000099,
	0 -8px 4px #00000066;
	font-family: "special";
	overflow: hidden;
	transition:all .4s, transform .4s cubic-bezier(.63,-1.07,.29,1.69);
	user-select: none;
	cursor: pointer;
}
.card::before{
	content: "";
	position: absolute;
	left: 50%;
	top: 3px;
	width: 95%;
	height: 2px;
	background-color: #fff;
	border-radius: 50%;
	filter: blur(1px);
	transform: translate(-50%,0);
	z-index: 0;
	opacity: .5;
	transition: .4s;
}
.card::after{
	content: "";
	position: absolute;
	left: 0;
	top: 0;
	width: 240px;
	height: 40px;
	background-image:
	linear-gradient(to right,transparent 20%, #ffffffaa 200%),
	linear-gradient(30deg,transparent 60%, #fff 100%);
	transform: rotate(-30deg) translate(-45px,0);
	transition: .4s cubic-bezier(.63,-1.07,.29,1.69);
}
.card:hover{
	color: #fff;
	text-shadow:
	0 0 1px #ffffff,
	0 0 2px #ffffff,
	0 0 16px #ffffff,
	0 0 32px #ffffff;
	box-shadow:
	0 20px 50px -15px #000 inset,
	0 -20px 50px -25px #ffffff88 inset,
	-2px 5px 10px #000000aa,
	-6px 15px 10px #00000088,
	-20px 36px 40px #00000066;
	background-color: #465e83;
	transform: rotateX(10deg);
}
.card:hover::before{
	top: 10px;
}
.card:hover::after{
	left: 50px;
}
.card:active{
	background-color: #1d2838;
}
#stars{
	position: fixed;
	left: 0;
	top: 0;
	z-index: -1;
}
.bg{
	position: fixed;
	left: 0;
	top: 0;
	width: 100%;
	height: 100%;
	z-index: -2;
	background-color: #0e0919;
	background-image: linear-gradient(to top, #98dbff77 -50%,transparent 100%);
}
</style>
</head>
<body>
<div class="container">
	<div class="card">Frantta</div>
	<div class="card">Obvious</div>
	<div class="card">Specific</div>
	<div class="card">fabulous</div>
	<div class="card">exciting</div>
	<div class="card">cool</div>
</div>
<canvas id="stars"></canvas>
<div class="bg"></div>
<script type="text/javascript">
!function (e,w){
	function Particle(option) {
		this.originOption = {
			el: "#myCanvas",// canvas 选择器 ( 可配置 )
			f: 1200, // 焦距 ( 可配置 )
			dis: 14000, // 视距 ( 可配置 )
			rY: 0, // 初始 y 轴旋转角度 ( 可配置 )
			rX: 0, // 初始 x 轴旋转角度 ( 可配置 )
			mode: 5, // 模式 ( 可配置 )
			preEmit: false, // 是否预运行 ( 可配置 )
			draggable: true, // 是否允许拖拽 ( 可配置 )
			pList: [], // 集中管理粒子 ( 可配置 )
			lightList: [], // 灯光队列
			mainWidth: w.innerWidth, // 画布宽
			mainHeight: w.innerHeight, // 画布高
			canvas: null, // canvas dom
			cx: null, // canvas2d 上下文对象
			emitterPos: [400, 400], // 发射器坐标
			nPs: 20, // 每秒发射的粒子数量
			timer: null, // 动画计时器
			cTimer: null, // 创建粒子计时器
			life: 5000, // 粒子生命 (ms)
			ms: 0, // 当前时间
			dur: 10, // 发射粒子间隔(需初始化)
			isPress: false, // 鼠标是否按下
			dragX: 0, // x 方向拖拽量
			dragY: 0, // y 方向拖拽量
			_currX: 0, // x 方向临时拖拽量
			_currY: 0 ,// y 方向临时拖拽量
			swing: 50, // 全局振幅
			freq: 1, // 全局振频
			userDis: false, // 用户是否设置视距
			userN: false, // 用户是否设置横纵数量
			zoomQuotiety: 30, // 滚轮缩放速度
			drawFace: true, // 是否绘制面(tCubic模式)
			drawSide: false, // 是否绘制线框(tCubic模式)
			drawAnchor: false ,// 是否绘制顶点(tCubic模式)
			glow: false,
			showTail: false, // 是否开启拖尾模式
		}
		Object.assign(this, this.originOption, option)
		;option.dis && (this.userDis = true)
		;(option.nX || option.nY) && (this.userN = true)
		this.init()
	}
	Particle.prototype.expend = function(obj) {Object.assign(this, obj)}
	Particle.prototype.expend({
		init() {
			this.dur = Math.floor(1000 / this.nPs) // 初始化粒子发射时间间隔
			this.dragY = this.rX * 180 / Math.PI
			this.dragX = this.rY * 180 / Math.PI
			this.canvas = e.querySelector(this.el)
			if(!this.canvas){
				throw Error("Please provide an enable canvas element selector for option 'el'")
				return false
			}
			if(this.canvas.isUsed){
				throw Error("Reduplicate canvas element, please provide another enable canvas element selector for option 'el', or use function 'destroy()' to remove this instance first!")
				return false
			}
			this.cx = this.canvas.getContext("2d")
			this.canvas.setAttribute("width",this.mainWidth)
			this.canvas.setAttribute("height",this.mainHeight)
			this.showTail && (this.canvas.style.mixBlendMode = "screen")
			this.canvas.isUsed = true // 占用
			this.emitterPos = [this.mainWidth / 2, this.mainHeight / 2]
			this.addEvent()
			this.emit()
		},
		addEvent() {
			this.windowResize = () => {
				this.mainWidth = w.innerWidth
				this.mainHeight = w.innerHeight
				this.canvas.setAttribute("width",this.mainWidth)
				this.canvas.setAttribute("height",this.mainHeight)
			}
			w.addEventListener("resize",this.windowResize)
		},
		emit() {
			this["mode"+this.mode]()
		},
		draw(frame,isStatic,isFromConner){
			var t = this.showTail ? 10 : 16
			if(isStatic){
				frame.call(this)
			}else{
				this.timer = setInterval(() => {
					this.ms = performance.now()
					this.cx.save()
					!this.showTail && this.cx.clearRect(0,0,this.mainWidth,this.mainHeight)
					this.showTail && (this.cx.fillStyle = "#00000011",this.cx.fillRect(0,0,this.mainWidth,this.mainHeight))
					if(!isFromConner){
						this.cx.translate(this.mainWidth / 2, this.mainHeight / 2)
					}
					frame()
					this.cx.restore()
				}, 16)
			}
		},
		// **********************  个性功能区
		star(option){
			// 输入中心坐标，尺寸，收缩量，是否星形，输出正多边形（星形）各个顶点依次的坐标
			var star = {
				x: 100,
				y: 100,
				isStar: true,	// 是否为星形
				n: 5,			// 边数
				shrink: .35,		// 收缩量
				size: 40,		// 长半径
				rotate: 0,
				// thickness: 40,
				// color: [180,50,80]
			}
			Object.assign(star,option)
			var anchors = []
			if(star.isStar){
				for(var i = 0; i < star.n * 2; i++){
					var step = Math.PI / star.n * i - Math.PI / 2 + star.rotate
					if(i % 2 == 0){
						anchors.push([
							Math.cos(step) * star.size + star.x,
							Math.sin(step) * star.size + star.y
						])
					}else{
						anchors.push([
							Math.cos(step) * star.size * star.shrink + star.x,
							Math.sin(step) * star.size * star.shrink + star.y
						])
					}
				}
			}else{
				for(var i = 0; i < star.n; i++){
					var step = Math.PI / star.n * i * 2 - Math.PI / 2 + star.rotate
					anchors.push([
						Math.cos(step) * star.size + star.x,
						Math.sin(step) * star.size + star.y
					])
				}
			}
			return anchors // 路径格式
		}
	})
	w.Particle = Particle
}(document,window)
</script>
<script type="text/javascript">
new Particle({
	el: "#stars",
	mode: 1,
	mode1(){
		let _this = this
		let starList = []
		let posList = []
		for(let i = 0; i < 100; i++){
			starList.push(this.star({
				x: Math.random() * this.mainWidth,
				y: Math.random() * this.mainHeight,
				size: Math.random() * 10 + 5,
				rotate: Math.floor(Math.random() * Math.PI * 2),
				n: Math.random() > .5 ? 5 : 4,
				isStar: Math.random() > .5 ? true : false
			}))
			let phase = Math.random() * 10
			posList.push({
				get offX(){
					return Math.sin(_this.ms / 3000 + phase) * 300
				},
				get offY(){
					return Math.cos(_this.ms / 2000 + phase) * 300
				},
			})
		}
		this.draw(() => {
			this.cx.fillStyle = "#ffffff"
			starList.forEach((l,index) => {
				this.cx.beginPath()
				l.forEach((p,i) => {
					this.cx[i == 0 ? 'moveTo' : 'lineTo'](p[0] + posList[index].offX,p[1] + posList[index].offY)
				})
				this.cx.closePath()
				this.cx.shadowBlur = 10
				this.cx.shadowColor = "#99f"
				this.cx.fill()
			})
		},false,true)
	}
})
var cards = Array.from(document.querySelectorAll(".card"))
cards.forEach((c,i) => {
	c.style.filter = `hue-rotate(${ i * 60 }deg)`
})
</script>
</body>
</html>
